package com.sushi.bigblog.web.controller;

import com.sushi.bigblog.filedb.DbEntry;
import com.sushi.bigblog.utils.Buffer;
import com.sushi.bigblog.web.service.BlogService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

/**
 * User: BianP
 * Date: 11-12-3
 */
@Controller
@RequestMapping(value = "/action")
public class BlogController {
    public static final int DEFAULT_OWNER = 101;
    private Logger logger = Logger.getLogger(getClass());

    @Autowired
    private BlogService blogService;

    /**
     * access: http://localhost/big-blog/blog/view/list
     * comes from class RequestMapping + method RequestMapping
     * @return
     */
    @RequestMapping(value = "/list/{offset}/{limit}", method = {RequestMethod.POST})
	public void doList(@PathVariable int offset, @PathVariable int limit, HttpServletResponse response) {
        Buffer buf = new Buffer();
        try {
            List<DbEntry> entries = blogService.getEntryList(offset, limit);

            response.setContentType("text/plain");
            OutputStream output = response.getOutputStream();
            output.write('[');
            for(DbEntry entry : entries) {
                int bufstart = buf.print((int) entry.getOffset());
                output.write(buf.buf(), bufstart, buf.size() - bufstart);
                if (entry != entries.get(entries.size() - 1)) {
                    output.write(',');
                }
            }
            output.write(']');
        } catch (IOException e) {
            try {
                response.sendError(404);
            } catch (IOException e1) {
                logger.error("get list failed", e1);
            }
        }
    }

    //
    // int to string
    //
    private static int itoa(byte[] buf, int val) {
        for(int i = buf.length - 1 ; i >= 0; --i) {
            buf[i] = (byte)('0' + (val % 10));
            val /= 10;
            if (val == 0) return i;
        }
        return 0;
    }

    @RequestMapping(value = "/save/{owner}", method = {RequestMethod.POST})
    public void doSave(@PathVariable int owner, HttpServletRequest request, HttpServletResponse response) {
        try {
            InputStream in = request.getInputStream();
            int len = request.getContentLength();
            if (len <= 0) {
                response.sendError(404);
            } else {
                byte[] bytes = new byte[len];
                int recvlen = 0;
                while(in.available() != 0 && recvlen < len) {
                    recvlen += in.read(bytes);
                }
                long id = blogService.saveBlog(bytes, owner, 0);
                logger.info(String.format("[saved] id=%d", id));
                response.getOutputStream().print(id);
            }
        } catch (IOException e) {
            logger.error("save blog failed", e);
        }
    }

    /*
    @RequestMapping(value = "/new", method = {RequestMethod.POST, RequestMethod.GET})
	public void doNew(HttpServletResponse response) {
        try {
            byte[] data = "白日依山尽，黄河入海流。欲穷千里目，更上一层楼。".getBytes("utf-8");
            // dicide zip or not
            if (data.length < COMPRESS_LIMIT) {
                long id = blogService.saveBlog(data, DEFAULT_OWNER, 0);
                response.getOutputStream().print(id);
            } else {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                GZIPOutputStream gzip = new GZIPOutputStream(bos);
                gzip.write(data);
                gzip.finish();
                bos.close();
                long id = blogService.saveBlog(bos.toByteArray(), DEFAULT_OWNER, Db.FLAG_GZIPPED);
                response.getOutputStream().print(id);
            }
        } catch (IOException e) {
            logger.error("new blog error", e);
        }
	}
    */

    @RequestMapping(value = "/view/{id}", method = {RequestMethod.POST})
	public void doView(@PathVariable long id, HttpServletResponse response) {
        response.setContentType("text/plain");
        response.setCharacterEncoding("utf-8");
        try {
            BlogService.Blog blog = blogService.getBlog(id);
            if (blog != null) {
                if (blog.isGZipped()) {
                    response.setHeader("Content-Encoding", "gzip");
                }
                response.getOutputStream().write(blog.getContent());
            } else {
                response.sendError(404);
            }
        } catch (IOException e) {
            logger.error("retieve blog failed", e);
        }
	}

    /**
     * access: http://localhost/big-blog/blog/view
     * comes from class RequestMapping
     * @return
     */
     @RequestMapping(method = {RequestMethod.GET})
	public ModelAndView doIndex() {
		return new ModelAndView("index");
	}
}
